from rest_framework import serializers
from goods.models import SKU, GoodsCategory, SPU, SPUSpecification, SpecificationOption, SKUSpecification, Brand, \
    SKUImage, GoodsChannel, GoodsChannelGroup
from django.db import transaction


class CategoriesSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = ['id', 'name']


class SPUSerializer(serializers.ModelSerializer):
    brand = serializers.StringRelatedField(read_only=True)
    brand_id = serializers.IntegerField()

    category1 = serializers.StringRelatedField()
    category1_id = serializers.IntegerField()
    category2 = serializers.StringRelatedField()
    category2_id = serializers.IntegerField()
    category3 = serializers.StringRelatedField()
    category3_id = serializers.IntegerField()

    class Meta:
        model = SPU
        fields = '__all__'


class SpecOptSerializer(serializers.ModelSerializer):
    spec = serializers.StringRelatedField(read_only=True)
    spec_id = serializers.IntegerField()

    class Meta:
        model = SpecificationOption
        fields = ('id', 'value', 'spec', 'spec_id')


class SPUSpecificationSerializer(serializers.ModelSerializer):
    # options = SpecOptSerializer(instance=SpecificationOption.objects.all())
    options = SpecOptSerializer(read_only=True, many=True)

    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()

    class Meta:
        model = SPUSpecification
        fields = '__all__'


class SKUSpecificationSerializer(serializers.Serializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()


class SkuViewSerialzer(serializers.ModelSerializer):
    category = serializers.StringRelatedField(read_only=True)
    category_id = serializers.IntegerField()

    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()

    specs = SKUSpecificationSerializer(read_only=True, many=True)
    options = SpecOptSerializer

    class Meta:
        model = SKU
        fields = '__all__'

        read_only_fields = ['spu']

    def create(self, validated_data):
        sid = transaction.savepoint()
        try:
            spu_id = validated_data['spu_id']
            spu_skus = SPU.objects.get(id=spu_id).sku_set.all()
            map_dic = {}
            for spu_sku in spu_skus:
                key = []
                for spec in spu_sku.specs.all():
                    key.append(spec.option_id)
                map_dic[tuple(key)] = spu_sku.id

            sku = SKU.objects.create(**validated_data)
            specs = self.context['request'].data['specs']
            key = []
            for spec in specs:
                key.append(spec['option_id'])
                spec['sku_id'] = sku.id
                SKUSpecification.objects.create(**spec)

            has_sku = map_dic.get(tuple(key))
            if has_sku:
                raise serializers.ErrorDetail('定义规格选项与sku_id={} 的商品完全一致'.format(has_sku))
        except:
            transaction.savepoint_rollback(sid)
            raise serializers.ValidationError("保存失败")
        else:
            transaction.savepoint_commit(sid)
            return sku

    def update(self, instance, validated_data):
        data = self.context['request'].data
        specs = data['specs']
        # 更新普通数据
        SKU.objects.filter(id=instance.id).update(**validated_data)
        [spec.delete() for spec in instance.specs.all()]
        for spec in specs:
            spec['sku_id'] = instance.id
            SKUSpecification.objects.create(**spec)
        return SKU.objects.get(id=instance.id)


class BrandSerializer(serializers.ModelSerializer):
    class Meta:
        model = Brand
        fields = '__all__'


class SKUImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = SKUImage
        fields = '__all__'


class GoodChannelSerializer(serializers.ModelSerializer):
    category = serializers.StringRelatedField(read_only=True)
    category_id = serializers.IntegerField()
    group = serializers.StringRelatedField(read_only=True)
    group_id = serializers.IntegerField()

    class Meta:
        model = GoodsChannel
        fields = '__all__'


class GoodsChannelGroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsChannelGroup
        fields = '__all__'
